package com.xdf.whiteaccount.aop;

import com.xdf.whiteaccount.dao.*;
import com.xdf.whiteaccount.entity.*;
import com.xdf.whiteaccount.enums.ConfigIntEnum;
import com.xdf.whiteaccount.enums.ResponseEnum;
import com.xdf.whiteaccount.exception.NotallowException;
import com.xdf.whiteaccount.service.CallService;
import com.xdf.whiteaccount.utils.Example;
import com.xdf.whiteaccount.vo.PlanDetailVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.math.BigDecimal;
import java.util.Date;
import java.util.Optional;

/**
 * @program: white-account
 * @description: 计划单
 * @author: 张柯
 * @create: 2021-05-19 17:25
 **/
@Component
@Slf4j
@Aspect
public class PlanServiceAspect extends AbstractAop {
    @Autowired
    private CallService callService;
    @Autowired
    private PlanMapper planMapper;
    @Autowired
    private SysConfigIntMapper sysConfigIntMapper;
    @Autowired
    private JrkbillsumMapper jrkbillsumMapper;
    @Autowired
    private ProductInfoMapper productInfoMapper;
    @Autowired
    private MeterLengthMapper meterLengthMapper;
    @Autowired
    private SpecificationMapper specificationMapper;
    @Autowired
    private WidthOfFabricMapper widthOfFabricMapper;
    @Autowired
    private WeightOfFabricMapper weightOfFabricMapper;

    @Pointcut("execution(* com.xdf.whiteaccount.service.PlanService.insert*(..))")
    public void insert() {
    }

    @Pointcut("execution(* com.xdf.whiteaccount.service.PlanService.update*(..))")
    public void update() {
    }

    @Pointcut("execution(* com.xdf.whiteaccount.service.PlanService.cancelByPrimaryKey(..))")
    public void delete() {
    }

    @Pointcut("execution(int com.xdf.whiteaccount.service.PlanService.setFinishedMark(..))")
    public void setFinished() {
    }

    /**
     * 新增编号
     *
     * @param joinPoint
     */
    @Before("insert()")
    @Transactional(rollbackFor = Exception.class)
    public void beforeInsert(JoinPoint joinPoint) {
        Object para = getParam1(joinPoint);
        if (para instanceof Plan) {
            Plan plan = (Plan) para;
            plan.setCreateUserId(getLoginUserId());
            plan.setPlanCode(callService.planCodeGen());
            plan.setId(null);
            plan.setState(1);
            plan.setUpload(0);
            if (plan.getIsMarking() == null) {
                plan.setIsMarking(false);
            }
            if (plan.getPlanDate() == null) {
                plan.setPlanDate(new Date());
            }
            if (StringUtils.isEmpty(plan.getBottomSupplierId())) {
                plan.setBottomSupplierId(null);
            }
            if (StringUtils.isEmpty(plan.getMaterialSupplierId())) {
                plan.setMaterialSupplierId(null);
            }
            if (StringUtils.isEmpty(plan.getMiddleSupplierId())) {
                plan.setMiddleSupplierId(null);
            }
            if (plan.getProcessingCost() == null) {
                plan.setProcessingCost(new BigDecimal(0));
            }
            if (plan.getGreyfabricPrice() == null) {
                plan.setGreyfabricPrice(new BigDecimal(0));
            }
            if (plan.getIsShowOrder() == null) {
                plan.setIsShowOrder(false);
            }
            //  以下操作内容：基础资料没有的自动添加,若果需要追加的话继续添加
            //  白坯规格
            if (StringUtils.isNotEmpty(plan.getMaterialSpecification())) {
                if (specificationMapper.countByExample(new Example().andEq("spec_name", plan.getMaterialSpecification())) <= 0) {
                    specificationMapper.insertSelective(Specification.builder().specName(plan.getMaterialSpecification()).build());
                }
            }
            //  下机克重
            if (StringUtils.isNotEmpty(plan.getLowWeight())) {
                if (weightOfFabricMapper.countByExample(new Example().andEq("wof_name", plan.getLowWeight())) <= 0) {
                    weightOfFabricMapper.insertSelective(WeightOfFabric.builder().wofName(plan.getLowWeight()).build());
                }
            }
            //  白坯克重
            if (StringUtils.isNotEmpty(plan.getGreyfabricWeight())) {
                if (weightOfFabricMapper.countByExample(new Example().andEq("wof_name", plan.getGreyfabricWeight())) <= 0) {
                    weightOfFabricMapper.insertSelective(WeightOfFabric.builder().wofName(plan.getGreyfabricWeight()).build());
                }
            }
            //  米长
            if (StringUtils.isNotEmpty(plan.getMeterLength())) {
                MeterLength meterLength = new MeterLength();
                meterLength.setMeter_length(plan.getMeterLength());
                if (CollectionUtils.isEmpty(meterLengthMapper.listQuery(meterLength))) {
                    meterLengthMapper.insertSelective(meterLength);
                }
            }
            //  下机门幅
            if (StringUtils.isNotEmpty(plan.getLowWidth())) {
                if (widthOfFabricMapper.countByExample(new Example().andEq("wof_name", plan.getLowWidth())) <= 0) {
                    widthOfFabricMapper.insertSelective(WidthOfFabric.builder().wofName(plan.getLowWidth()).build());
                }
            }
            //  以下是根据配置判断是否执行校验,校验的内容写在异常提示里面
            int config = Optional.ofNullable(sysConfigIntMapper.selectByPrimaryKey(ConfigIntEnum.PLAN_SAVE_VALIDATE.getField()))
                    .map(SysConfigInt::getConfigValue)
                    .orElse(0);
            if (config > 0) {
                Long count = planMapper.countByExample(
                        new Example()
                                .andEq("order_code", plan.getOrderCode())
                                .andEq("contact_company_id", plan.getContactCompanyId())
                                .andEq("m_height", plan.getmHeight())
                                .andEq("meter_length", plan.getMeterLength())
                                .andEq("greyfabric_weight", plan.getGreyfabricWeight())
                                .andEq("greyfabric_width", plan.getGreyfabricWidth())
                                .andEq("greyfabric_specification", plan.getGreyfabricSpecification())
                                .andEq("material_specification", plan.getMaterialSpecification())
                                .andEq("material_lot_no", plan.getMaterialLotNo())
                                .andEq("plan_date",plan.getPlanDate())
                );
                Assert.state(Optional.ofNullable(count).orElse(0L) <= 0, "客户，订单号，毛高，米长，头份，原料规格，批次号，制单日期已有重复单据！");
            }
        }
    }

    /**
     * 修改
     *
     * @param joinPoint
     */
    @Before("update()")
    public void beforeUpdate(JoinPoint joinPoint) {
        Object para = getParam1(joinPoint);
        if (para instanceof Plan) {
            Plan plan = (Plan) para;
            Assert.state(plan.getId() != null, "没有主键,无法修改！");
            Assert.state(!Optional.ofNullable(plan).map(Plan::getMarkFinished).orElse(false), "已完工不允许修改!");
            Plan prev = planMapper.selectByPrimaryKey(plan.getId());
            Assert.state(!Optional.ofNullable(prev).map(Plan::getIsAudit).orElse(false), ResponseEnum.IS_AUDIT.getName());
            if (StringUtils.isEmpty(plan.getBottomSupplierId())) {
                plan.setBottomSupplierId(null);
            }
            if (plan.getIsMarking() == null) {
                plan.setIsMarking(false);
            }
            if (StringUtils.isEmpty(plan.getMaterialSupplierId())) {
                plan.setMaterialSupplierId(null);
            }
            if (StringUtils.isEmpty(plan.getMiddleSupplierId())) {
                plan.setMiddleSupplierId(null);
            }
            if (plan.getProcessingCost() == null) {
                plan.setProcessingCost(new BigDecimal(0));
            }
            if (plan.getGreyfabricPrice() == null) {
                plan.setGreyfabricPrice(new BigDecimal(0));
            }
            if (plan.getIsShowOrder() == null) {
                plan.setIsShowOrder(false);
            }
            plan.setUpload(0);
        }
    }

    /**
     * 删除前事件
     *
     * @param joinPoint
     */
    @Before("delete()")
    @Transactional(rollbackFor = Exception.class)
    public void beforeCancel(JoinPoint joinPoint) {
        Object param = getParam1(joinPoint);
        if (param instanceof Long) {
            Plan record = planMapper.selectByPrimaryKey((Long) param);
            Assert.notNull(record, ResponseEnum.NO_ORDER.getName());
            Assert.state(1 == record.getState(), ResponseEnum.CANCEL_ORDER.getName());
            Assert.state(!Optional.ofNullable(record).map(Plan::getIsAudit).orElse(false), ResponseEnum.IS_AUDIT.getName());
            Assert.state(!Optional.ofNullable(record).map(Plan::getMarkFinished).orElse(false), "已完工不允许作废!");
            Assert.state(jrkbillsumMapper.countByExample(new Example().andEq("planid", record.getId())) <= 0L, "已有入库数不允许删除！");
        }
    }

    /**
     * 完工前校验
     *
     * @param joinPoint
     * @return
     */
    @Before("setFinished()")
    public void afterSetFinished(JoinPoint joinPoint) throws Exception {
        Object param1 = getParam1(joinPoint);
        Object param2 = getParam2(joinPoint);
        if (param1 instanceof Long) {
            Plan record = planMapper.selectByPrimaryKey((Long) param1);
            Assert.state(!Optional.ofNullable(record).map(Plan::getIsAudit).orElse(false), ResponseEnum.IS_AUDIT.getName());
        }
        if (param1 instanceof Long && param2 instanceof Boolean) {
            Long id = (Long) param1;
            Boolean isFinished = (Boolean) param2;
            if (isFinished) {
                PlanDetailVO vo = callService.getPlanDtl(id);
                Assert.notNull(vo, "无法获取库存数据,检查存储过程");
                Integer config = Optional.ofNullable(sysConfigIntMapper.selectByPrimaryKey(ConfigIntEnum.PLAN_FINISHED_CHECK.getField()))
                        .map(SysConfigInt::getConfigValue)
                        .orElse(1);
                if (config != 1) return;
                BigDecimal remainKilo = Optional.ofNullable(vo).map(PlanDetailVO::getRemainKilo).orElse(new BigDecimal(0D));
                BigDecimal remainPairs = Optional.ofNullable(vo).map(PlanDetailVO::getRemainPairs).orElse(new BigDecimal(0D));
                if (remainKilo.doubleValue() != 0) {
                    throw new NotallowException("库存公斤不为0,不允许完工！");
                }
                if (remainPairs.doubleValue() != 0) {
                    throw new NotallowException("库存匹数不为0,不允许完工！");
                }
            }
        }
    }
}